package io.renren.common.utils.image;



import io.renren.modules.nuaa.entity.ContentEntity;
import io.renren.modules.oss.cloud.OSSFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;

/**
 * 操作图片工具类
 * author: 峰影
 **/
public class DrawImageUtil {

    /**
     * @param image   原图
     * @param content 内容对象
     * @return void
     * @Description 向图片中填充内容
     * @Author 峰影
     */
    public static void drawContentEntity(BufferedImage image, ContentEntity content) throws Exception {

        int imgWidth = image.getWidth();
        int imgHeight = image.getHeight();

        // 根据百分比计算画笔开始位置的坐标
        BigDecimal x = new BigDecimal(content.getWidthPer() * imgWidth).setScale(4,
                BigDecimal.ROUND_HALF_UP);

        BigDecimal y = new BigDecimal(content.getHeightPer() * imgHeight).setScale(4,
                BigDecimal.ROUND_HALF_UP);

        Graphics2D g = (Graphics2D) image.getGraphics();
        if (!content.isImg()) {
            // 填充文字 从左往右
            DrawImageUtil.setStringToImg(content.getContent(), g,
                    x.intValue(), y.intValue(),
                    content.getFontFamily(),
                    content.getFontStyle(),
                    content.getFontSize(),
                    content.getFontSpace(),
                    content.getFontColor(),
                    content.getFontDirection());
        } else {
            // 填充图片
            URL url = new URL(content.getContent());
            //ImageIO.read(url);
            try{
            DrawImageUtil.mergePendant(g, ImageIO.read(url),
                    x.intValue(), y.intValue(), content.getImgWidth(), content.getImgHeight(), 1);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }

    /**
     * @param image         -  BufferedImage对象
     * @param targetImgPath - 目标文件路径
     * @param suffix        - 文件格式
     * @return void
     * @Description 把图片无损再次保存
     * @Author 峰影
     **/
    public static String saveLossLessImage(BufferedImage image, String targetImgPath, String suffix) throws Exception {
        //不压缩图片质量进行保存
        ImageWriter writer = ImageIO.getImageWritersBySuffix(suffix).next();
        ImageWriteParam imageWriteParam = writer.getDefaultWriteParam();
        imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        //0-1范围 越大质量越高
        imageWriteParam.setCompressionQuality(1);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        writer.setOutput(new MemoryCacheImageOutputStream(output));
        writer.write(null, new IIOImage(image, null, null), imageWriteParam);
        writer.dispose();

        //最终图片保存到本地
        FileOutputStream file = new FileOutputStream(targetImgPath);
        file.write(output.toByteArray());
        file.close();
        //返回本地固定地址
        return "http://localhost/img/test.jpg";

        //上传到oss
//        String extension =  "png";
//        String url = OSSFactory.build().uploadSuffix(imageToBytes(image, "png"), extension);
//        output.close();
//        return url;

    }

    /**
     * @param content    - 内容
     * @param g          - Graphics2D对象
     * @param x          - 坐标
     * @param y          - 坐标
     * @param fontFamily - 字体
     * @param fontStyle  - 字体样式
     * @param fontSize   - 字体大小
     * @param fontSpace  - 字体间距
     * @param fontColor  - 字体颜色
     * @return void
     * @Description 填充文字内容从左往右
     * @Author 峰影
     **/
    public static void setStringToImg(String content, Graphics2D g, Integer x, Integer y, String fontFamily,
                                      Integer fontStyle, Integer fontSize, Integer fontSpace, Color fontColor, Integer fontDirection) {
        Font font = new Font(fontFamily, fontStyle, fontSize);
        if (null == fontSpace) {
            //每个字的间距 默认用字体大小来分割
            fontSpace = fontSize;
        }
        System.out.println(content);
        // 判断content字符串,从第几位开始是数字类型
        int numIndex = 0;
        for (int i = 0; i < content.length(); i++) {
            if (content.charAt(i)=='-') {
                numIndex = i;
                break;
            }
        }

        for (int i = 0; i < content.length(); i++) {
            char singleWordChart = content.charAt(i);
            // 如果遇到·符号，字体换成宋体
            if (singleWordChart == '·') {
                font = new Font("宋体", fontStyle, fontSize);
            }else{
                font = new Font(fontFamily, fontStyle, fontSize);
            }
            AttributedString singleWord = new AttributedString(String.valueOf(singleWordChart));
            g.setStroke(new BasicStroke(2.5f));
            g.setColor(fontColor);
            g.setFont(font);
            /* 消除java.awt.Font字体的锯齿 */
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            /* 消除java.awt.Font字体的锯齿 */
            singleWord.addAttribute(TextAttribute.FONT, font, 0,
                    String.valueOf(singleWordChart).length());
            AttributedCharacterIterator singleWordIterator = singleWord.getIterator();

            Integer newX = x;
            Integer newY = y;
            //从左往右
            if(fontDirection == 0){
                if (i > 0) {
                    newX = x + (i * fontSpace);
                    //特殊符号间距处理
                    if(singleWordChart == '/' || singleWordChart == '-'){
                        newX = x + (i * fontSpace) + (fontSize/4);
                    }
                    if(singleWordChart == '·'){
                        newX = x + (i * fontSpace) + (fontSize/48);
                    }
                    // 判断是数字，间距使用26
                    if(numIndex > 0 && i >= numIndex) {
                        //数字前的中文使用fontSpace作为间距, 从第一位数字开始使用18
                        newX = x + ((numIndex * fontSpace) + ((i - numIndex) * (int)(fontSpace*0.667)));
                    }
                    //证书编码里的第2位置处理
                    if(singleWordChart=='D' || singleWordChart == 'A'){
                        newX = newX - 4;
                    }
                    //证书编码里的第17位置处理
                    if(i==16 && singleWordChart=='G'){
                        // 往左移动一点
                        newX = newX - 12;
                    }

                }
                g.drawString(singleWordIterator, newX, y);
            }
            //从上往下
            if(fontDirection == 1){
                if (i > 0) {
                    newY = y + (i * fontSpace);
                }
                g.drawString(singleWordIterator, x, newY);
            }
        }
    }

    /**
     * @param g2d          底图
     * @param pendantImage 挂件图
     * @param x            距离左上角的X偏移量
     * @param y            距离左上角的Y偏移量
     * @param alpha        透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @return void
     * @Description 两张图片合并为一张图片
     * @Author 峰影
     */
    public static void mergePendant(Graphics2D g2d, BufferedImage pendantImage, int x, int y, int w, int h, float alpha) {
        //获取挂件图像的宽高
        //int pendantImageWidth = pendantImage.getWidth();
        //int pendantImageHeight = pendantImage.getHeight();
        //int pendantImageWidth = 360;
        //int pendantImageHeight = 500;
        int pendantImageWidth = w;
        int pendantImageHeight = h;
        //实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        //绘制图像
        g2d.drawImage(pendantImage, x, y, pendantImageWidth, pendantImageHeight, null);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    }


    /**
     * 转换BufferedImage 数据为byte数组
     *
     * Image对象
     * @param format
     * image格式字符串.如"jpg","png"
     * @return byte数组
     */
    public static byte[] imageToBytes(BufferedImage bImage, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, format, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }
}
